﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once
#include "GcmpModelInterface.h"
#include "IExternalObject.h"
#include "OwnerPtr.h"
#include "IPlane.h"
#include "IPolygon.h"
#include "IGraphicsStyleData.h"
#include "ElementCreationOptions.h"

namespace gcmp
{
    class IDocument;
    class IExternalDatas;
    struct CurveIndexInPolygon;

    /// \brief 填充区域数据信息
    struct FilledRegionData
    {   
        /// \brief 构造FilledRegionData
        ///
        /// \param pDocument    文档指针
        /// \param modelViewId 填充区域所在视图的ElementId，在其他视图下不显示
        /// \param opPlane 填充区域所在平面
        /// \param opPolygon 填充区域轮廓
        /// \paramfilledPatternName 填充模式的名字
        FilledRegionData(IDocument *pDocument,
            const ElementId& modelViewId,
            OwnerPtr<IPlane> opPlane,
            OwnerPtr<IPolygon> opPolygon,            
            const std::wstring& fillPatternName)
            : FilledRegionDocument(pDocument)
            , ModelViewId(modelViewId)
            , FilledRegionPlane(TransferOwnership(opPlane))
            , FilledRegionPolygon(TransferOwnership(opPolygon))
            , FillPatternName(fillPatternName)
            , IsBorderVisible(true)
            , IsMask(false)
            , FillColor(Color(245, 245, 245, 255))
            , FillScale(1.0)
            , FilledRegionBoundaryCurveStyleMap(nullptr)
        {
        }

        IDocument* FilledRegionDocument; ///<  文档指针
        ElementId ModelViewId;   ///<  填充区域所在视图的ElementId     
        OwnerPtr<IPlane> FilledRegionPlane;///< 填充区域所在平面
        OwnerPtr<IPolygon> FilledRegionPolygon; ///<  填充区域轮廓
        std::wstring FillPatternName;  ///<  填充模式的名字
        bool IsBorderVisible;   ///<  填充区域边界线是否可见性
        bool IsMask;            ///<  填充区域是否遮罩
        Color FillColor;    ///<  填充图案的颜色及透明度
        double FillScale;   ///<  缩放倍数,填充图案的缩放倍数是填充模式中的缩放倍数和该缩放倍数的累乘效果
        std::map<CurveIndexInPolygon, ElementId>* FilledRegionBoundaryCurveStyleMap; ///<  填充区域边界样式信息。 如果为空，使用默认样式。
    };

    /// \brief 填充区域，在指定的闭合轮廓，生成一块根据填充样式绘制的区域
    class GCMP_MODEL_INTERFACE_EXPORT IFilledRegion : public IExternalObject
    {
        DEFINE_CAST_DERIVED(gcmp::IFilledRegion, gcmp::IExternalObject)
    public:
        /// \brief 析构函数
        virtual ~IFilledRegion() {} 

        /// \brief 创建填充区域
        ///
        /// \param[in] pDocument 文档指针
        /// \param[in] modelViewId 填充区域所在视图的ElementId，在其他视图下不显示
        /// \param[in] filledRegionTypeId 填充区域类型的ElementId
        /// \param[in] opPlane 填充区域所在平面
        /// \param[in] opPolygon 填充区域轮廓
        /// \param[in] pFilledRegionBoundaryCurveStyleMap 填充区域边界样式信息。 如果为空，使用默认样式。
        /// \return 如果成功，则返回填充区域的指针，如果失败，则为nullptr
        static IFilledRegion* Create(IDocument *pDocument,
            const ElementId& modelViewId,
            const ElementId& filledRegionTypeId,
            OwnerPtr<IPlane> opPlane,
            OwnerPtr<IPolygon> opPolygon,
            const std::map<CurveIndexInPolygon, ElementId>* pFilledRegionBoundaryCurveStyleMap = nullptr);

        /// \brief 创建填充区域
        ///
        /// \param[in] filledRegionData 填充区域数据信息
        /// \param[in] eco 创建方式，缺省为正常方式
        /// \return 如果成功，则返回填充区域的指针，如果失败，则为nullptr
        static IFilledRegion* Create(FilledRegionData& filledRegionData, ElementCreationOptions eco = ElementCreationOptions::Normal);

        /// \brief 设置填充区域所在平面，一个填充区域的三维几何表示由一个平面和一个二维多边形表示
        ///
        /// \param[in] opPlane 填充区域所在平面，不能为空
        virtual bool SetPlane(OwnerPtr<IPlane> opPlane) = 0;

        /// \brief 获取填充区域所在平面，一个填充区域的三维几何表示由一个平面和一个二维多边形表示
        ///
        /// \return 填充区域所在平面，不能为空
        virtual const IPlane* GetPlane() const = 0;

        /// \brief 设置填充区域轮廓，一个填充区域的三维几何表示由一个平面和一个二维多边形表示
        ///
        /// \param[in] opPolygon 填充区域轮廓，不能为空
        virtual bool SetBoundary(OwnerPtr<IPolygon> opPolygon) = 0;

        /// \brief 获取填充区域轮廓，一个填充区域的三维几何表示由一个平面和一个二维多边形表示
        ///
        /// \return 填充区域轮廓，不能为空
        virtual const IPolygon* GetBoundary() const = 0;  
      
        /// \brief 设置所属视图的ElementId
        ///
        /// \param[in] viewId 所属视图的ElementId
        virtual void SetModelViewId(const ElementId &viewId) = 0;

        /// \brief 获取所属视图的ElementId
        ///
        /// \return 所属视图的ElementId
        virtual ElementId GetModelViewId() const = 0;

        /// \brief 获取当前填充区域边界线的可见性
        ///
        /// \return 可见返回true，不可见返回false
        virtual bool IsBorderVisible() const = 0;

        /// \brief 设置当前填充区域边界线的可见性
        ///
        /// \param bVisible 可见性
        virtual void SetIsBorderVisible(bool bVisible) = 0;

        /// \brief 设置当前填充区域边界线的样式
        ///
        /// \param curveIndex 曲线在多边形中的索引
        /// \param styleElementId 边界线的样式id
        /// \return 设置成功返回true， 失败返回false
        virtual bool SetBoundaryStyle(const CurveIndexInPolygon &curveIndex, const ElementId& styleElementId) = 0;

        /// \brief 返回当前填充区域边界线的样式
        ///
        ///        如果一条边界线样式被重载过，那么返回重载过的样式，否则不返回该边界线的样式信息
        /// \return 填充区域边界线的样式
        virtual std::map<CurveIndexInPolygon, ElementId> GetBoundaryStyle() const = 0;

        /// \brief 得到填充区域关联更新变化Id
        ///
        ///  该变化不包含样式变化
        /// \return 填充区域关联更新变化Id
        virtual RegenDataId GetRegionChangedRdId() const = 0;

        /// \brief 获取Implementation Uid
        ///
        /// \return UniIdentity 返回ImplementationUid
        static UniIdentity GetImplementationUid();

        /// \brief 获取填充区域的所有外部扩展数据
        ///
        /// \return 返回填充区域的所有外部扩展数据
        virtual const IExternalDatas* GetExternalDatas() const = 0;

        /// \brief 获取填充区域的所有外部扩展数据，用户可以通过此函数返回值对外部扩展数据进行修改
        ///
        /// \return 返回填充区域的所有外部扩展数据
        virtual IExternalDatas* GetExternalDatas() = 0;

    public:
        /// \brief 获取填充图案的颜色和透明度,透明度通过rgba中的a来表示
        ///
        /// ----------------
        /// | / / / / / / /|
        /// |/ / / / / / / |
        /// ----------------
        /// 填充区域在绘制的时候会根据填充模式的描述,生成一些图案,比如上图中的斜线,并将这些图案按照一定规则重复排列塞满区域,这个颜色就是指这些图案的颜色
        /// \return 填充图案的颜色
        virtual Color GetColor() const = 0;

        /// \brief 设置填充图案的颜色和透明度,透明度通过rgba中的a来表示
        ///
        /// ----------------
        /// | / / / / / / /|
        /// |/ / / / / / / |
        /// ----------------
        /// 填充区域在绘制的时候会根据填充模式的描述,生成一些图案,比如上图中的斜线,并将这些图案按照一定规则重复排列塞满区域,这个颜色就是指这些图案的颜色
        /// \param[in] color 填充图案的颜色
        virtual void SetColor(const Color &color) = 0;

        /// \brief 获得填充图案的智能颜色模式
        ///
        /// \return 获得的填充图案的智能颜色模式
        virtual SmartColorMode GetSmartColorMode() const = 0;

        /// \brief 设置填充图案的智能颜色模式
        /// 
        /// \param smartColorMode 设置的填充图案的智能颜色模式
        /// return 成功与否
        virtual bool SetSmartColorMode(const SmartColorMode& smartColorMode) = 0;

        /// \brief 获取填充模式名字
        ///
        /// \return 填充模式名字
        virtual std::wstring GetFillPatternName() const = 0;

        /// \brief 设置新的填充模式
        ///
        /// \param newPatternName 新填充模式名字
        /// \return 成功返回true，失败返回false；当新填充模式名字和当前填充模式名字相同，或者无法通过新填充模式名字找到填充模式时，设置失败
        virtual bool SetFillPatternName(const std::wstring& newPatternName) = 0;

        /// \brief 获取填充图案的线宽
        ///
        /// \return 填充图案的线宽
        virtual double GetLineWidth() const = 0;

        /// \brief 设置填充图案的线宽
        ///
        ///  填充图案线宽模式默认使用像素模式，所以lineWidth需要大于1，但是因为希望以后支持世界单位模式，所以类型设计为double
        /// \param lineWidth 填充图案的线宽
        /// \return 成功返回true，失败返回false
        virtual bool SetLineWidth(double lineWidth) = 0;


        /// \brief 设置填充区域是否遮罩
        ///
        /// \param isMask 是否遮罩
        /// \return 成功返回true，失败返回false
        virtual bool SetIsMask(bool isMask) = 0;

        /// \brief 填充区域是否遮罩
        ///
        /// \return 返回true表示遮罩，否则不遮罩
        virtual bool IsMask() const = 0;

        /// \brief 设置缩放倍数
        ///
        ///填充图案的最终缩放倍数是该设置的缩放倍数与填充模式设置的缩放倍数的累乘，如果是填充模式目标是绘图模式，还会乘以视图比例
        /// \param scale 缩放倍数
        /// \return bool true：设置成功 false：设置失败
        virtual bool SetScale(double scale) = 0;

        /// \brief 获取缩放倍数
        /// \return 缩放倍数
        virtual double GetScale() const = 0;

        /// \brief 设置是否可以被选择
        /// 
        /// \param isSelectable true-可以被选择；false-不可以被选择
        /// \return true 设置成功，false设置失败
        virtual bool SetIsSelectable(bool isSelectable) = 0;

        /// \brief 获取是否可以被选择
        /// 
        /// \return true-可以被选择；false-不可以被选择
        virtual bool IsSelectable() const = 0;

        /// \brief 获取填充样式ID
        /// \return 样式ID
        virtual ElementId GetGraphicsStyleId() const = 0;
       
    };

}
